/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
// $File: pfile.hpp$
// $Revision: 1.1 $
//
// PEG file encapsulation.
//
// $Author: volpicg $
//
// Copyright (c) 2002, 2003, 2004 Swell Software, Inc.
//              All Rights Reserved.
//
// Unauthorized redistribution of this source code, in whole or part,
// without the express written permission of Swell Software, Inc.
// is strictly prohibited.
//
// Notes:
//
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/

#ifndef PEGFILE_HPP_
#define PEGFILE_HPP_

#if defined(PEG_FILE_CLASS)

/*--------------------------------------------------------------------------*/
// Enable this flag if the filesystem is on a removeable media devices 
// such as USB stick or SD memory card and you want PEG to update the media 
// when files change.  
//
// For performance reasons, some file systems (FILEX) don't update the media 
// until a buffer is sufficiently filled. In this type of system, if the
// user performs a hot swap of the media, all file updates which are 
// currently cached will be lost.
/*--------------------------------------------------------------------------*/
#define PEG_MANAGE_MEDIA_UPDATE



/*--------------------------------------------------------------------------*/
// File modes. These are mapped to the operating systems file modes
// for read/write/create/truncate/binary open operations. Your target
// file system may or may not support all of these modes.
/*--------------------------------------------------------------------------*/
const PEGUINT PEG_FILEMODE_RO   = 0x0001;   // r - read only must exist
const PEGUINT PEG_FILEMODE_RW   = 0x0002;   // r+ - read/write must exist
const PEGUINT PEG_FILEMODE_WTC  = 0x0004;   // w - write only truncate/create
const PEGUINT PEG_FILEMODE_RWTC = 0x0008;   // w+ - read/write truncate/create
const PEGUINT PEG_FILEMODE_WC   = 0x0010;   // a - write only append/create
const PEGUINT PEG_FILEMODE_RWC  = 0x0020;   // a+ - read/write append/create
const PEGUINT PEG_FILEMODE_BIN  = 0x0040;   // optional binary mode

const PEGUINT PEG_FILEMODE_MASK = 0x007f;
const PEGUINT PEG_FILEMODE_WRITE_MASK = 0x003e;

/*--------------------------------------------------------------------------*/
// File seek constants
/*--------------------------------------------------------------------------*/
#define PEG_FILE_SEEK_SET       0x01
#define PEG_FILE_SEEK_CUR       0x02
#define PEG_FILE_SEEK_END       0x04

/*--------------------------------------------------------------------------*/
// The maximum length for a file name
/*--------------------------------------------------------------------------*/
#if defined(MAX_PATH)
#define PEG_MAX_PATH MAX_PATH
#else
#define PEG_MAX_PATH 256
#endif  // MAX_PATH

/*--------------------------------------------------------------------------*/
// Common type for a file stream descriptor
/*--------------------------------------------------------------------------*/
#if defined(PEG_FILE_ANSI_C)
#include <stdio.h>
#define PEG_FILE_T          FILE*
#define PEG_EOF             EOF
#elif defined(PEG_FILE_WIN32)
#define PEG_FILE_T          HANDLE
#define PEG_EOF             -1
#elif defined(PEG_FILE_FILEX)
#include "fx_api.h"
#define PEG_FILE_T          FX_FILE*
#define PEG_MEDIA_T         FX_MEDIA*
#define PEG_EOF             -1
#define PEG_FILE_SUCCESS    FX_SUCCESS
#define PEG_FILE_NOT_FOUND  FX_NOT_FOUND

#if defined(PEG_MANAGE_MEDIA_UPDATE)
#include "fx_user.h"

// These two FILEX flags force media updates internally to FILEX
//#if !defined(FX_FAULT_TOLERANT)
#define PEG_FILE_MANUAL_CACHE_UPDATE
//#endif

#endif // PEG_MANAGE_MEDIA_UPDATE

#elif defined(PEG_FILE_POSIX)
#define PEG_FILE_T          int
#define PEG_EOF             -1
#else
#error "Please select a file interface."
#endif


/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
class PegFile
{
    public:
        PegFile();
       #if defined(PEG_FILE_FILEX)
        PegFile(PEG_MEDIA_T pMedia);
       #endif
        virtual ~PegFile();

        virtual void Close(void);
        virtual PEGBYTE GetByte(void);
        const char* GetFileName(void) const { return mpFileName; }
        virtual PEGUINT GetMode(void) const { return mMode; }
        virtual PEGBOOL IsEOF(void);
        virtual PEGBOOL IsOpen(void);

        virtual PEGBOOL Open(const char* pFileName,
                             const PEGUINT Mode = PEG_FILEMODE_RO);
        virtual PEGUINT Read(void *pBuffer, PEGUINT Size);
        PEGUINT ReadRecords(void *pRecs, PEGUINT RecSize,
                            PEGUINT Count);
        virtual PEGUINT ReadString(char* pBuffer, PEGUINT Size);
        virtual PEGBOOL Seek(PEGINT Offset, PEGUINT Start);

       #if defined(PEG_FILE_FILEX)
        virtual void SetMedia(PEG_MEDIA_T pMedia) 
        {
            mpMedia = pMedia;
        }
       #endif

        virtual PEGUINT Size();

        virtual PEGUINT Write(const void *pBuffer, const PEGUINT Size = 1);
        PEGUINT WriteRecords(const void* pRecs, PEGUINT RecSize,
                             PEGUINT Count);
        virtual PEGUINT WriteString(const char *pBuffer);

       #if defined(PEG_UNICODE)
        virtual PEGUINT WriteString(const PEGCHAR *pBuffer);
       #endif

    protected:
       #if defined(PEG_FILE_ANSI_C)
        char* ConstructANSICModeString(const PEGUINT Mode);
       #elif defined(PEG_FILE_WIN32)
        void ConstructWin32ModeString(const PEGUINT Mode,
                                      PEGULONG& Creation, PEGULONG& Access);
       #elif defined(PEG_FILE_FILEX)
        PEGUINT DetermineFileXMode(const PEGUINT Mode);
       #endif

        PEG_FILE_T      mpFile;

       #if defined(PEG_FILE_FILEX)
        PEG_MEDIA_T     mpMedia;
        FX_FILE         mFile;
       #endif

        char* mpFileName;
        PEGUINT mMode;
};

#endif  // PEG_FILE_CLASS

#endif  // PEGFILE_HPP_

